package com.jstyle.rtk_ota_objc.rtk_ota_plugin;

import android.app.Activity;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;

import androidx.annotation.NonNull;

import com.realsil.sdk.dfu.DfuConstants;
import com.realsil.sdk.dfu.model.DfuConfig;
import com.realsil.sdk.dfu.model.DfuProgressInfo;
import com.realsil.sdk.dfu.model.OtaDeviceInfo;
import com.realsil.sdk.dfu.model.Throughput;
import com.realsil.sdk.dfu.utils.ConnectParams;
import com.realsil.sdk.dfu.utils.DfuAdapter;
import com.realsil.sdk.dfu.utils.GattDfuAdapter;

import org.apache.commons.codec.digest.DigestUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import io.flutter.Log;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;

/** RtkOtaPlugin */
public class RtkOtaPlugin implements FlutterPlugin, MethodCallHandler,ActivityAware {
  private MethodChannel channel;
  private DfuAdapter.DfuHelperCallback dfuHelperCallback = new DfuAdapter.DfuHelperCallback() {
    @Override
    public void onStateChanged(int i) {
      super.onStateChanged(i);
      if(i == DfuAdapter.STATE_INIT_OK){
        if(TextUtils.isEmpty(address)){
          //没有传入Mac地址,搜索设备（一般不会）
          sendMessage("10,0");
        }else{
          //连接设备
          sendMessage("11,0");
          new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
              boolean flag = connectRemoteDevice();
              Log.e("test","sendMessage: 11," + flag);
            }
          },2000);
        }
      }
      if (i == DfuAdapter.STATE_PREPARED){
        sendMessage("3,0");
        //准备完成
        isConnected = true;
        handler.sendEmptyMessage(0);
      }else if(i == DfuAdapter.STATE_DISCONNECTED || i == DfuAdapter.STATE_CONNECT_FAILED){
        //已断开、连接失败
        if(i == DfuAdapter.STATE_DISCONNECTED){
          sendMessage("9,0");
        }
        if(i == DfuAdapter.STATE_CONNECT_FAILED){
          sendMessage("2,0");
        }
        isConnected = false;
      }else if(i == DfuAdapter.STATE_BACKCONNECT_COMPLETED){
        isConnected = true;
      }else if(i == DfuAdapter.STATE_OTA_PROCESSING){

      }
    }


    @Override
    public void onTargetInfoChanged(OtaDeviceInfo otaDeviceInfo) {
      super.onTargetInfoChanged(otaDeviceInfo);
    }

    @Override
    public void onError(int i, int i1) {
      super.onError(i, i1);
      //失败重新升级
      sendMessage("7,0");
      if(null != dfuAdapter){
        dfuAdapter.disconnect();
      }
      new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
          boolean flag = connectRemoteDevice();
        }
      },2000);
    }

    @Override
    public void onProcessStateChanged(int i, Throughput throughput) {
      super.onProcessStateChanged(i, throughput);
      if(i == DfuConstants.PROGRESS_PREPARE_OTA_ENVIRONMENT){
        //正在准备OTA环境中
        sendMessage("4,0");
      }
      if(i == DfuConstants.PROGRESS_START_DFU_PROCESS){
        //进入OTA环境
        sendMessage("5,0");
      }
    }

    @Override
    public void onProgressChanged(DfuProgressInfo dfuProgressInfo) {
      super.onProgressChanged(dfuProgressInfo);
      sendMessage("6,"+dfuProgressInfo.getProgress());
      //进度
//        String.format("%d%%",dfuProgressInfo.getProgress());
      if(dfuProgressInfo.getProgress() == 100){
        //升级完成，等待手表程序自动写入
        if(dfuAdapter != null){dfuAdapter.disconnect();}
        //进行设备重连/或退出页面
        sendMessage("8,0");

      }
    }
  };
  private GattDfuAdapter dfuAdapter;
  private Activity activity;
  private String address;
  //固件升级文件
  private String filePath;
  //UI升级文件
  private String colorPath;
  //资源升级文件
  private String resPath;
  //Dfu是否连接中
  private boolean isConnected = false;
  //开始升级，异步转主线程
  private Handler handler = new Handler(){
    @Override
    public void handleMessage(@NonNull Message msg) {
      super.handleMessage(msg);
      switch (msg.what){
        case 0:
          boolean flag = startEnterOta();
          Log.e("test","handleMessageL " + flag);
          break;
        case 1:
          break;
      }

    }
  };

  @Override
  public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
    channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "rtk_ota_plugin");
    channel.setMethodCallHandler(this);
  }

  //通知Flutter端 // 1 状态(1连接成功 2 连接失败 3 准备完成 4 正在准备OTA环境中
  // 5 进入OTA环境 6 升级中  7 升级失败，重新升级 8 升级成功 9 设备断开 10 没有传入Mac地址
  // 11 连接设备中) 2 进度
  private void sendMessage(String text) {
    Log.e("test","sendMessage: " + text);
    handler.post(new Runnable() {
      @Override
      public void run() {
        channel.invokeMethod("sendMessage",text);
      }
    });
  }

  private void initDfuAdapter(){
//    Log.e("test","initDfuAdapter： " + address + " " + filePath);
    dfuAdapter = GattDfuAdapter.getInstance(activity);
    dfuAdapter.initialize(dfuHelperCallback);
  }

  private boolean connectRemoteDevice(){
    if(TextUtils.isEmpty(address)){
      return false;
    }else{
      ConnectParams.Builder builder = new ConnectParams.Builder()
              .address(address)
              .reconnectTimes(3);
      dfuAdapter.connectDevice(builder.build());
      return true;
    }
  }

  private boolean connectRemoteDevice(String address){
    if(TextUtils.isEmpty(address)){
      return false;
    }else{
      ConnectParams.Builder builder = new ConnectParams.Builder()
              .address(address)
              .reconnectTimes(3);
      dfuAdapter.connectDevice(builder.build());
      return true;
    }
  }

  //开始升级
  private boolean startEnterOta(){
//    Log.e("test","startEnterOta1： " + address);
//    Log.e("test","startEnterOta2： " + filePath);
    if(TextUtils.isEmpty(address) || TextUtils.isEmpty(filePath)){
      if(TextUtils.isEmpty(address)){
        sendMessage("10,0");
      }
      if(TextUtils.isEmpty(filePath)){
        sendMessage("12,0");
      }
      return false;
    }
    DfuConfig config = new DfuConfig();
    config.setChannelType(DfuConfig.CHANNEL_TYPE_GATT);
    config.setAddress(address);
    config.setFilePath(filePath);
    config.setVersionCheckEnabled(false);
    dfuAdapter.startOtaProcedure(config,dfuAdapter.getOtaDeviceInfo(),true);
    return true;
  }

  @Override
  public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
    Log.e("test","onMethodCall: " + call.method);
    if (call.method.equals("getPlatformVersion")) {
      result.success("Android " + android.os.Build.VERSION.RELEASE);
    } else if(call.method.equals("initDfuAdapter")){
      if(call.hasArgument("address")){
        address = call.argument("address");
      }
      if(call.hasArgument("path")){
        setFilePath(call.argument("path"));
      }
      if(activity != null){
        initDfuAdapter();
      }
      result.success("");
    } else if(call.method.equals("setAddress")){
      if(call.hasArgument("address")){
        address = call.argument("address");
      }
    } else if(call.method.equals("setFilePath")){
      if(call.hasArgument("path")){
        setFilePath(call.argument("path"));
      }
    } else if(call.method.equals("connectRemoteDevice")){
      if(call.hasArgument("address")){
        address = call.argument("address");
      }
      boolean flag = connectRemoteDevice(address);
      result.success(flag+"");
    } else if(call.method.equals("getColorPath")){
      if(colorPath != null && colorPath.isEmpty()){
        result.success("");
      }else{
        result.success(colorPath+"");
      }
    } else if(call.method.equals("md5")){
//      List<Integer> values = new ArrayList<>();
      String pa = "";
      if(call.hasArgument("path")){
        pa = (String)call.argument("path");
      }
      if(TextUtils.isEmpty(pa)){
        result.success("1,path is Null");
      }else{
        result.success(md5(pa));
      }
    }else {
      result.notImplemented();
    }
  }

  private String md5(String path){
    File binFile = new File(path);
    if(!binFile.exists()){
      return "1,binFile not exists";
    }
    byte[] fileValue = ZipUtils.readFile(binFile);
    if(fileValue == null){
      return "1,file is not have";
    }
    byte[] binByte = new byte[fileValue.length - 16];
    System.arraycopy(fileValue,0,binByte,0,binByte.length);
    byte[] md5Value = DigestUtils.md5(binByte);
    return byte2Hex(md5Value);
  }

  private String byte2Hex(byte[] data){
    if(data != null && data.length > 0){
      StringBuffer sb = new StringBuffer(data.length);
      for(byte tmp: data){
        sb.append(String.format("%02X",tmp));
      }
      return "2," + sb.toString();
    }
    return "1,data is null";
  }


  byte[] checkFile(byte[] values){
//    File file = new File(colorPath);
//    byte[] binByte = ZipUtils.readFile(file);
//    Log.e("test","binByte: " + ((binByte==null)?0:binByte.length));
//    byte[] sendValue = new byte[binByte.length - 16];
//    System.arraycopy(binByte,0,sendValue,0,sendValue.length);
//    Log.e("test","sendValue: " + ((sendValue==null)?0:sendValue.length));
//    byte[] value = ZipUtils.checkUpdateFile(sendValue,DigestUtils.md5(sendValue),0,false);
//    Log.e("test","binByte: " + ((value==null)?0:value.length));
//    return value;
    //方案一
    return DigestUtils.md5(values);
  }


  private void setFilePath(String path){

    try {
      File deleteFile = new File(ZipUtils.getFromPath(activity)+"ota/");
      if(deleteFile.exists()){
        deleteFile.delete();
      }
    }catch (Exception e){

    }
    //本地
//    path = "J2203_03_V001_1_20230901.zip";
//    ZipUtils.copyFileFromAssets(activity,path);
//    ZipUtils.upZipFile(ZipUtils.getFromPath(activity)+path,ZipUtils.getFromPath(activity)+"ota/");
    //服务器
   ZipUtils.upZipFile(path, ZipUtils.getFromPath(activity)+"ota/");
    File file = new File(ZipUtils.getFromPath(activity)+"ota/");
    if(!file.exists()){
      return;
    }
    File[] files = file.listFiles();
    for (int i = 0; i < files.length; i++) {
      Log.e("test","fileName: " + files[i].getName());
      if(files[i].getName().contains("app")){
        filePath = files[i].getAbsolutePath();
      }
      if(files[i].getName().contains("color565")){
        colorPath = files[i].getAbsolutePath();
      }
    }
  }

  @Override
  public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
    channel.setMethodCallHandler(null);
  }

  @Override
  public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
    activity = binding.getActivity();
    
  }

  @Override
  public void onDetachedFromActivityForConfigChanges() {

  }

  @Override
  public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {

  }

  @Override
  public void onDetachedFromActivity() {
      activity = null;
  }
}
